#include "user_main.h"

static const char *TAG = "ota demo";
static EventGroupHandle_t s_event_group;

int shortdown(void)
{
    ESP_LOGW(TAG, "===== SHOART DOWN =====");
    xEventGroupSetBits(s_event_group, KEY_SHORT_DOWN);
    return 0;
}
    
int longdown(void)
{
    ESP_LOGW(TAG, "===== LONG DOWN =====");
    xEventGroupSetBits(s_event_group, KEY_LONG_DOWN);
    return 0;
}

void system_monitor(void *argv)
{
    Gpio_Init();
    set_key_shortDown_callback(200, shortdown);
    set_key_longDown_callback(2000, longdown);

    while (1)
    {
        KEY_scanf();
        LED_control();
        vTaskDelay(100/portTICK_RATE_MS);
    }
}

void Networl_init(void *argv)
{
    system_status_t *sys_sta = get_sys_sta();
    my_wifi_t wifi_info = {
        .ssid = "HONOR-0415PD",
        .password = "pf0105602"
    };

    ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
    if (wifi_init_sta(&wifi_info)){
        ESP_LOGE(TAG, "CONNECT TO AP FAIL");
        sys_sta->network_sta = -1;
    }
    else {
        sys_sta->network_sta = 1;
        ESP_LOGW(TAG, "WIFI connect success");
    }
    delete_task("Networl_init");
}

void HeapStack_monitor(void *argv)
{
    task_handle_managa_t *task_handle_cur = NULL;
    task_handle_managa_t *task_handle_haed = get_task_handle_haed();
    while (1)
    {
        printf("\n");
        ESP_LOGI(TAG, "free_heap_size: %d KB", esp_get_free_heap_size() / 1024);
        ESP_LOGI(TAG, "minimum_free_heap_size: %d KB", esp_get_minimum_free_heap_size() / 1024);

        for (task_handle_cur = task_handle_haed; task_handle_cur != NULL; 
                task_handle_cur = task_handle_cur->next)
        {
            if (task_handle_cur->handle != NULL) {
                ESP_LOGI(TAG, "%s stack:%d B", task_handle_cur->name, uxTaskGetStackHighWaterMark(task_handle_cur->handle) * 4);
            }
        }
        printf("\n");
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
}

int edition_compare(const char* pszStr1, const char* pszStr2)
{
	if (pszStr1 == NULL || pszStr2 == NULL) {
		return 0;
	}
	int nCurPos = 0, nCapPos=-1;
	const char* pszTmp1 = pszStr1;
	const char* pszTmp2 = pszStr2;
	while ((*pszTmp1 != '\0') && (*pszTmp2 != '\0') && (*pszTmp1 == *pszTmp2)) {	
		nCurPos++;									//找到第一个处不相同出现的位置
		pszTmp1++;
		pszTmp2++;
		if (*pszTmp1 == '.') {
			nCapPos = nCurPos;						//记录最近的‘.’的位置
		}
	}
	if (*pszTmp1 == '\0' && *pszTmp2 == '\0') { // 两个字符串相等
		return 0;
	} else if(*pszTmp1 == '\0'){
		return -1;
	} else if(*pszTmp2 == '\0'){
		return 1;
	}else{ // 两个字符串不相等，比较大小
		pszTmp1 = pszStr1 + nCapPos + 1;
		pszTmp2 = pszStr2 + nCapPos + 1;

		int pszNub1=strtol(pszTmp1,NULL,10);
		int pszNub2=strtol(pszTmp2,NULL,10);

		return (pszNub1 - pszNub2);
	}
}

void ota_task(void *argv)
{
    system_status_t *sys_sta = get_sys_sta();
    const esp_app_desc_t *app_desc = esp_ota_get_app_description();
    char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
    EventBits_t bits = 0;
    int recv = 0;

    while (1)
    {
        bits = xEventGroupWaitBits(s_event_group,
                    KEY_SHORT_DOWN | KEY_LONG_DOWN,
                    pdTRUE,
                    pdFALSE,
                    portMAX_DELAY);
        if (bits == KEY_SHORT_DOWN) {
            esp_http_client_config_t config = {
                .method = HTTP_METHOD_GET,
                .url = "http://norep.gitee.io/ota/ota_test/version",
                .user_data = local_response_buffer,
            };
            memset(local_response_buffer, 0, MAX_HTTP_OUTPUT_BUFFER);
            recv = http_client_GET(&config);
            // if (recv > 0) {
            //     printf("rec:%d\n%s\n", recv, local_response_buffer);
            // }

            if (local_response_buffer[strlen(local_response_buffer) - 1] == '\n') 
                local_response_buffer[strlen(local_response_buffer) - 1] = '\0';

            recv = edition_compare(local_response_buffer, app_desc->version);
            if (recv > 0) {
                sys_sta->ota_sta = 1;
                ESP_LOGW(TAG, "%s -> %s", app_desc->version, local_response_buffer);
                recv = start_ota("http://norep.gitee.io/ota/ota_test/ota.bin");
                if (recv <= 0) {
                    sys_sta->ota_sta = 0;
                     ESP_LOGE(TAG, "%s -> %s : update fail", app_desc->version, local_response_buffer);
                }
            }
            else {
                ESP_LOGW(TAG, "local ver: %s >= remote ver:%s", app_desc->version, local_response_buffer);
            }
        }
        vTaskDelay(100/portTICK_RATE_MS);
    }
}

void app_main()
{
    ESP_ERROR_CHECK(nvs_flash_init());
    s_event_group = xEventGroupCreate();

    const esp_app_desc_t *app_desc = esp_ota_get_app_description();
    ESP_LOGI(TAG, "app_version:%s", app_desc->version);
    
    printf("free_heap_size: %d KB\n", esp_get_free_heap_size() / 1024);
    printf("minimum_free_heap_size: %d KB\n", esp_get_minimum_free_heap_size() / 1024);

    new_task(HeapStack_monitor, "HeapStack_monitor", 1024, NULL, 21);
    new_task(Networl_init, "Networl_init", 1024 * 2, NULL, 22);
    new_task(system_monitor, "system_monitor", 1024, NULL, 23);
    new_task(ota_task, "ota_task", 1024 * 5, NULL, 24);

    ESP_LOGI(TAG, "Run");
}
